<template>
  <div>
    <!--//上传头像，不带修剪-->
    <a-upload
      v-if="uploadAvatarType === 1"
      name="files"
      listType="picture-card"
      class="avatar-uploader"
      :show-upload-list="false"
      :headers="this.token"
      :beforeUpload="beforeUpload"
      :disabled="disabled"
      accept=".png,.jpg,jpeg"
      :action="uploadService"
      @change="handleChange"
    >
      <img
        v-if="imageUrl && imageUrl !== ''"
        :src="imageUrl"
        alt="avatar"
        style="max-width:300px;max-height: 140px;"
      />
      <div v-else>
        <a-icon :type="loading ? 'loading' : 'plus'" />
        <div class="ant-upload-text">上传</div>
      </div>
    </a-upload>
    <!--//上传头像，带修剪功能-->
    <div
      v-if="uploadAvatarType === 2"
      :class="{ 'ant-upload-preview': imageUrl }"
      @click="edit(1)"
    >
      <div v-if="imageUrl" class="mask">
        <a-icon type="plus" />
      </div>
      <img v-if="imageUrl" :src="imageUrl" />
      <div
        :class="{ 'upload-disabled': disabled }"
        class="ant-upload-plus"
        v-else
      >
        <a-icon type="plus" />
        <div class="ant-upload-text">上传</div>
      </div>
    </div>
    <a-modal
      v-if="uploadAvatarType === 2"
      title="上传头像"
      :visible="visible"
      :maskClosable="false"
      :confirmLoading="confirmLoading"
      :width="800"
      :footer="null"
      @cancel="cancelHandel"
    >
      <a-row>
        <a-col :xs="24" :md="12" :style="{ height: '350px' }">
          <vue-cropper
            ref="cropper"
            :img="options.img"
            :info="true"
            :autoCrop="options.autoCrop"
            :autoCropWidth="options.autoCropWidth"
            :autoCropHeight="options.autoCropHeight"
            :fixedBox="options.fixedBox"
            @realTime="realTime"
          >
          </vue-cropper>
        </a-col>
        <a-col :xs="24" :md="12" :style="{ height: '350px' }">
          <div class="avatar-upload-preview">
            <img :src="previews.url" :style="previews.img" />
          </div>
        </a-col>
      </a-row>
      <br />
      <a-row>
        <a-col :lg="2" :md="2">
          <a-upload
            name="file"
            :headers="this.token"
            :beforeUpload="beforeUploadFile"
            :showUploadList="false"
          >
            <a-button icon="upload">选择图片</a-button>
          </a-upload>
        </a-col>
        <a-col :lg="{ span: 1, offset: 2 }" :md="2">
          <a-button icon="plus" @click="changeScale(1)" />
        </a-col>
        <a-col :lg="{ span: 1, offset: 1 }" :md="2">
          <a-button icon="minus" @click="changeScale(-1)" />
        </a-col>
        <a-col :lg="{ span: 1, offset: 1 }" :md="2">
          <a-button icon="undo" @click="rotateLeft" />
        </a-col>
        <a-col :lg="{ span: 1, offset: 1 }" :md="2">
          <a-button icon="redo" @click="rotateRight" />
        </a-col>
        <a-col :lg="{ span: 2, offset: 6 }" :md="2">
          <a-button type="primary" :loading="uploading" @click="finish('blob')">
            {{ uploading ? "正在上传" : "保存" }}
          </a-button>
        </a-col>
      </a-row>
    </a-modal>
  </div>
</template>

<script>
import reqwest from "reqwest";
import { VueCropper } from "vue-cropper";
import { mapState, mapActions } from "vuex";
import { getToken } from "@/utils/token";
function getBase64(img, callback) {
  const reader = new FileReader();
  reader.addEventListener("load", () => callback(reader.result));
  reader.readAsDataURL(img);
}
export default {
  components: { VueCropper },
  data() {
    return {
      uploadAvatarType: this.avatarType, //1，不带剪切图像   2，带剪切图像
      token: { token: getToken() },
      fileList: [], // 上传成功返回的路径信息
      imageUrl: "", // 上传到本地Base64图片路径
      previewVisible: false,
      previewImage: "",
      loading: false,
      uploadService: this.$globalConfig.uploadService + "/base/upload", //上传服务器地址
      uploadPath: this.$globalConfig.uploadPath + "/file/", // 图片路径服务器地址
      preview: {},
      option: {
        img: "",
        info: true,
        size: 1,
        outputType: "jpeg",
        canScale: false,
        autoCrop: true,
        // 只有自动截图开启 宽度高度才生效
        autoCropWidth: 180,
        autoCropHeight: 180,
        fixedBox: true,
        // 开启宽度和高度比例
        fixed: true,
        fixedNumber: [1, 1]
      },
      visible: false,
      id: null,
      confirmLoading: false,
      uploading: false,
      options: {
        img: "",
        autoCrop: true,
        autoCropWidth: 200,
        autoCropHeight: 200,
        fixedBox: true
      },
      previews: {},
      model: false,
      modelSrc: "",
      imgBase64: ""
    };
  },
  props: {
    imgURL: {
      type: String,
      default: ""
    },
    avatarType: {
      type: Number,
      default: 2
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    imgURL: {
      handler(newData, oldData) {
        if (newData) {
          this.imageUrl = this.uploadPath + newData;
        } else {
          this.imageUrl = "";
        }
      },
      // 代表在wacth里声明了imgURL这个方法之后立即先去执行handler方法
      immediate: true,
      deep: true
    }
  },
  methods: {
    // ---------不剪切图片----------
    beforeUpload(file) {
      const isJpgOrPng =
        file.type === "image/jpeg" || file.type === "image/png";
      if (!isJpgOrPng) {
        this.$message.error("只能上传jpg/png格式图片");
      }
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error("文件超过2M了");
      }
      return isJpgOrPng && isLt2M;
    },
    handleChange(info) {
      if (info.file.status === "uploading") {
        this.loading = true;
        return;
      }
      if (info.file.response.status !== 200) {
        this.$message.error("上传失败，检查服务是否正常或者重新上传");
        return;
      }
      if (info.file.status === "done") {
        getBase64(info.file.originFileObj, imageUrl => {
          this.imageUrl = imageUrl;
          this.imgBase64 = imageUrl;
          this.loading = false;
        });

        this.fileListMap(info);
      }
    },
    fileListMap(info) {
      this.fileList = info.fileList.map((obj, index) => {
        if (obj.response.status === 200) {
          return { name: obj.name, data: obj.response.data[0] };
        }
      });
      this.$emit("getAvatar", this.fileList);
    },
    // -------------剪切图片------------
    edit(id) {
      if (this.disabled) return
      this.visible = true
      this.id = id
      this.options.img = ''
    },
    close() {
      this.id = null;
      this.visible = false;
    },
    cancelHandel() {
      this.close();
    },
    changeScale(num) {
      num = num || 1;
      this.$refs.cropper.changeScale(num);
    },
    rotateLeft() {
      this.$refs.cropper.rotateLeft();
    },
    rotateRight() {
      this.$refs.cropper.rotateRight();
    },
    beforeUploadFile(file) {
      const reader = new FileReader();
      // 把Array Buffer转化为blob 如果是base64不需要
      // 转化为base64
      reader.readAsDataURL(file);
      reader.onload = () => {
        this.options.img = reader.result;
      };
      // 转化为blob
      // reader.readAsArrayBuffer(file)

      return false;
    },

    // 上传图片（点击上传按钮）
    finish(type) {
      const _this = this;
      const formData = new FormData();
      // 输出
      if (type === "blob") {
        this.$refs.cropper.getCropBlob(data => {
          console.log(data);
          const img = window.URL.createObjectURL(data);
          this.model = true;
          this.modelSrc = img;
          formData.append("files", data);
          this.handleUpload(formData);
        });
      } else {
        this.$refs.cropper.getCropData(data => {
          this.model = true;
          this.modelSrc = data;
        });
      }
    },

    // 提交上传图片
    handleUpload(formData) {
      this.uploading = true;
      reqwest({
        url: this.uploadService,
        method: "post",
        type: "json",
        processData: false,
        data: formData,
        headers: this.token,
        contentType: "application/json",
        crossOrigin: true,
        success: res => {
          if (res.status == 200) {
            this.$message.success("上传成功");
            this.setavatar(res.data[0]);
            let obj = { name: res.data[0], data: res.data[0] };
            this.fileList.push(obj);
            this.$emit("getAvatar", this.fileList);
            this.uploading = false;
            this.visible = false;
          } else {
            this.$message.error("上传失败，检查服务是否正常或者重新上传");
          }
        },
        error: () => {
          this.uploading = false;
          this.$message.error("上传失败");
        }
      });
    },
    realTime(data) {
      console.log(data);
      this.previews = data;
    },
    setavatar(url) {
      this.imageUrl = this.uploadPath + url;
    },
    getBase64Img() {
      let _this = this;
      //添加的情况，直接拿到图片base64格式
      if (this.imgBase64 === "") {
        //修改的情况，需要拿到服务器图片，再转换成base64格式
        this.convertImgToBase64(this.imageUrl, url => {
          // debugger;
          _this.$emit("asyncBase64", url);
        });
      } else {
        _this.$emit("asyncBase64", this.imgBase64);
      }
    },
    convertImgToBase64(url, callback) {
      let canvas = document.createElement("canvas"),
        ctx = canvas.getContext("2d"),
        img = new Image();
      img.crossOrigin = "anonymous"; //解决Canvas.toDataURL 图片跨域问题
      img.onload = () => {
        // debugger;
        canvas.height = img.height;
        canvas.width = img.width;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        let ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase(); // 获取到图片的格式
        let dataURL = canvas.toDataURL("image/" + ext); // 得到base64 编码的 dataURL
        callback && callback(dataURL);
        canvas = null;
      };
      img.src = url;
    }
  }
};
</script>

<style scoped lang="less">
.avatar-upload-wrapper {
  height: 200px;
  width: 100%;
}

.ant-upload-plus {
  width: 104px;
  height: 104px;
  background-color: #fafafa;
  border: 1px dashed #d9d9d9;
  border-radius: 4px;
  cursor: pointer;
  transition: border-color 0.3s ease;
  text-align: center;
  &:hover {
    border-color: #1890ff;
  }
  .ant-upload-text {
    line-height: 30px;
  }
  .anticon {
    padding-top: 20px;
  }
}

.ant-upload-preview {
  position: relative;
  // margin: 0 auto;
  width: 160px;
  // max-width: 180px;
  border-radius: 50%;
  box-shadow: 0 0 4px #ccc;

  .upload-icon {
    position: absolute;
    top: 0;
    right: 10px;
    z-index: 1;
    font-size: 1.4rem;
    padding: 0.5rem;
    background: rgba(222, 221, 221, 0.7);
    border-radius: 50%;
    border: 1px solid rgba(0, 0, 0, 0.2);
  }
  .mask {
    opacity: 0;
    position: absolute;
    background: rgba(0, 0, 0, 0.4);
    cursor: pointer;
    transition: opacity 0.4s;

    &:hover {
      opacity: 1;
    }

    i {
      font-size: 2rem;
      position: absolute;
      top: 50%;
      left: 50%;
      margin-left: -1rem;
      margin-top: -1rem;
      color: #d6d6d6;
    }
  }

  img,
  .mask {
    width: 160px;
    height: 160px;
    border-radius: 50%;
    overflow: hidden;
  }

  .ant-avatar {
    cursor: pointer;
  }
}
.avatar-upload-preview {
  position: absolute;
  top: 50%;
  transform: translate(50%, -50%);
  width: 180px;
  height: 180px;
  border-radius: 50%;
  box-shadow: 0 0 4px #ccc;
  overflow: hidden;

  img {
    width: 100%;
    height: 100%;
  }
}
.upload-disabled:hover {
  cursor: not-allowed;
}
</style>
